package org.locker.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingReceiver;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import lombok.RequiredArgsConstructor;
import org.locker.common.core.exception.ServiceException;
import org.locker.common.core.utils.MapstructUtils;
import org.locker.common.core.utils.StringUtils;
import org.locker.common.mybatis.core.page.PageQuery;
import org.locker.common.mybatis.core.page.TableDataInfo;
import org.locker.config.WxPayProperties;
import org.locker.domain.Device;
import org.locker.domain.ManagerConfig;
import org.locker.domain.Position;
import org.locker.domain.bo.PositionBo;
import org.locker.domain.vo.ManagerConfigVo;
import org.locker.domain.vo.PositionVo;
import org.locker.mapper.DeviceMapper;
import org.locker.mapper.ManagerConfigMapper;
import org.locker.mapper.PositionMapper;
import org.locker.service.IDeviceService;
import org.locker.service.IPositionService;
import org.locker.system.domain.SysUser;
import org.locker.system.mapper.SysUserMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 场地信息Service业务层处理
 *
 * @author winnie
 * @date 2023-10-11
 */
@RequiredArgsConstructor
@Service
public class PositionServiceImpl extends ServiceImpl<PositionMapper, Position> implements IPositionService {

    private final PositionMapper baseMapper;
    private final ManagerConfigMapper managerConfigMapper;
    private final SysUserMapper sysUserMapper;
    private final WxPayService wxPayService;
    private final WxPayProperties properties;
    private final IDeviceService deviceService;

    /**
     * 查询场地信息
     */
    @Override
    public PositionVo queryById(Long positionId) {
        PositionVo positionVo = baseMapper.selectVoById(positionId);
        //维护分润信息
        ManagerConfig managerConfig = managerConfigMapper.selectOne(Wrappers.<ManagerConfig>lambdaQuery()
            .eq(ManagerConfig::getPositionId, positionId));
        if (ObjectUtil.isNotNull(positionVo) && ObjectUtil.isNotNull(managerConfig)) {
            positionVo.setAgentUserId(managerConfig.getParentManagerId());
            positionVo.setAgentRate(managerConfig.getParentRate());
            positionVo.setManageUserId(managerConfig.getManagerId());
            positionVo.setManageRate(managerConfig.getRate());
        }
        return positionVo;
    }

    /**
     * 查询场地信息列表
     */
    @Override
    public TableDataInfo<PositionVo> queryPageList(PositionBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<Position> lqw = buildQueryWrapper(bo);
        Page<PositionVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        List<PositionVo> records = result.getRecords();
        Set<Long> positionIdSet = records.stream().map(PositionVo::getPositionId).collect(Collectors.toSet());
        Map<Long, ManagerConfigVo> managerConfigVoMap = new HashMap<Long, ManagerConfigVo>();
        if (CollUtil.isNotEmpty(positionIdSet)) {
            List<ManagerConfigVo> managerConfigVos =
                managerConfigMapper.selectVoList(Wrappers.<ManagerConfig>lambdaQuery()
                    .in(ManagerConfig::getPositionId, positionIdSet));
            managerConfigVoMap =
                managerConfigVos.stream().collect(Collectors.toMap(ManagerConfigVo::getPositionId, Function.identity()));

        }
        List<SysUser> sysUsers = sysUserMapper.selectList();
        Map<Long, String> userMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId, SysUser::getUserName));
        for (PositionVo record : records) {
            Long positionId = record.getPositionId();
            ManagerConfigVo managerConfigVo = managerConfigVoMap.get(positionId);
            if (ObjectUtil.isNull(managerConfigVo)) {
                continue;
            }
            record.setAgentUserId(managerConfigVo.getParentManagerId());
            record.setAgentUserName(userMap.get(managerConfigVo.getParentManagerId()));
            record.setAgentRate(managerConfigVo.getParentRate());
            record.setManageUserId(managerConfigVo.getManagerId());
            record.setManageUserName(userMap.get(managerConfigVo.getManagerId()));
            record.setManageRate(managerConfigVo.getRate());
            record.setFinanceUserName(userMap.get(record.getFinanceUserId()));
            record.setDeviceUserName(userMap.get(record.getDeviceUserId()));
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询场地信息列表
     */
    @Override
    public List<PositionVo> queryList(PositionBo bo) {
        LambdaQueryWrapper<Position> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<Position> buildQueryWrapper(PositionBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<Position> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getName()), Position::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getDescribe()), Position::getDescribe, bo.getDescribe());
        lqw.eq(StringUtils.isNotBlank(bo.getLocation()), Position::getLocation, bo.getLocation());
//        lqw.like(StringUtils.isNotBlank(bo.getUsername()), Position::getUsername, bo.getUsername());
//        lqw.eq(StringUtils.isNotBlank(bo.getPhone()), Position::getPhone, bo.getPhone());
        lqw.eq(bo.getLongitude() != null, Position::getLongitude, bo.getLongitude());
        lqw.eq(bo.getLatitude() != null, Position::getLatitude, bo.getLatitude());
        lqw.eq(StringUtils.isNotBlank(bo.getWorkTime()), Position::getWorkTime, bo.getWorkTime());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), Position::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getBelongingPlace()), Position::getBelongingPlace, bo.getBelongingPlace());
        return lqw;
    }

    /**
     * 新增场地信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(PositionBo bo) {
        Position add = MapstructUtils.convert(bo, Position.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setPositionId(add.getPositionId());
        }

        BigDecimal rate = bo.getManageRate().add(bo.getAgentRate());
        if (rate.compareTo(BigDecimal.valueOf(100)) > 0) {
            throw new ServiceException(StrUtil.format("该场地代理商分润比例{}+管理员分润比例{}大于100！", bo.getAgentRate(), bo.getManageRate()));
        }

        BigDecimal spiltRate = bo.getSpiltRate();
        if (spiltRate != null) {
            if (spiltRate.compareTo(BigDecimal.valueOf(30)) > 0) {
                throw new ServiceException("微信分账比例最高设置30%");
            }
        }
        //添加微信分账用户
        addToWxPayReceivers(bo);
        //维护分润信息
        ManagerConfig managerConfig = new ManagerConfig();
        managerConfig.setPositionId(add.getPositionId());
        managerConfig.setManagerId(bo.getManageUserId());
        managerConfig.setRate(bo.getManageRate());
        managerConfig.setParentManagerId(bo.getAgentUserId());
        managerConfig.setParentRate(bo.getAgentRate());
        managerConfig.setShareType("rate");
        managerConfigMapper.insert(managerConfig);
        return flag;

    }

    /**
     * 添加微信分账用户
     * @param bo
     */
    private void addToWxPayReceivers(PositionBo bo) {
        if (StringUtils.isNotBlank(bo.getOpenid())) {
            ProfitSharingReceiver.ProfitSharingReceiverBuilder receiverBuilder = ProfitSharingReceiver.newBuilder();
            ProfitSharingReceiver receiver = receiverBuilder
                .appid(properties.getAppId())
                .type("PERSONAL_OPENID")
                .account(bo.getOpenid())
                .relationType("PARTNER").build();
            try {
                wxPayService.getProfitSharingV3Service().addProfitSharingReceiver(receiver);
            } catch (WxPayException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 修改场地信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(PositionBo bo) {
        Position update = MapstructUtils.convert(bo, Position.class);
        validEntityBeforeSave(update);
        boolean b = baseMapper.updateById(update) > 0;
        //维护分润信息
        ManagerConfig managerConfig = managerConfigMapper.selectOne(Wrappers.<ManagerConfig>lambdaQuery()
            .eq(ManagerConfig::getPositionId, bo.getPositionId()));
        managerConfig.setManagerId(bo.getManageUserId());
        managerConfig.setRate(bo.getManageRate());
        managerConfig.setParentManagerId(bo.getAgentUserId());
        managerConfig.setParentRate(bo.getAgentRate());
        BigDecimal rate = bo.getManageRate().add(bo.getAgentRate());
        if (rate.compareTo(BigDecimal.valueOf(100)) > 0) {
            throw new ServiceException(StrUtil.format("该场地代理商分润比例{}+管理员分润比例{}大于100！", bo.getAgentRate(), bo.getManageRate()));
        }

        BigDecimal spiltRate = bo.getSpiltRate();
        if (spiltRate != null) {
            if (spiltRate.compareTo(BigDecimal.valueOf(30)) > 0) {
                throw new ServiceException("微信分账比例最高设置30%");
            }
        }
        //添加微信分账用户
        addToWxPayReceivers(bo);

        managerConfigMapper.updateById(managerConfig);

        //修改所有这个场地下面设备是否显示二维码
        deviceService.lambdaUpdate().eq(Device::getPositionId,update.getPositionId()).set(Device::getIsShowMp,update.getIsShowMp()).update();
        //批量去更新公众号二维码
        deviceService.updateMpQrCodeByPostion(update);
        return b;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(Position entity) {
        Long positionId = entity.getPositionId();
        String name = entity.getName();
        LambdaQueryWrapper<Position> queryWrapper = Wrappers.<Position>lambdaQuery().eq(Position::getName, name);
        if (ObjectUtil.isNotNull(positionId)) {
            queryWrapper.ne(Position::getPositionId, positionId);
        }
        long count = this.count(queryWrapper);
        //场地名称唯一性判断
        if (count > 0) {
            throw new ServiceException(StrUtil.format("该场地名称:{}已存在!", name));
        }
    }

    /**
     * 批量删除场地信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }
}
